﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using Fany.Libs.AsynchSocketLib;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Net;
using System.Xml;

namespace AMStudio.Driver
{
    public class LmiCamera : IDisposable
    {
        protected ExceptionManager ExManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

        //private DefaultTraceListener DebugConsole = new DefaultTraceListener();
        private Process process = Process.GetCurrentProcess();

        private string ip_address = "127.0.0.1";
        private int tcp_port = 0;
        private Socket sock;
        private ClientInfo client;
        private string user = "admin";
        private string password = "";

        public delegate void CameraDataReceivedHandler(object sender, CameraArgs e);
        public event CameraDataReceivedHandler OnDataReceived;

        public delegate void CameraConnectClosedHandler(object sender, EventArgs e);
        public event CameraConnectClosedHandler OnConnectClosed;

        public delegate void CameraConnectedHandler(object sender, EventArgs e);
        public event CameraConnectedHandler OnConnected;
        //private bool disposed = false;

        public LmiCamera()
        {

        }

        public LmiCamera(string ip_s, int p_n, string usr, string pa)
            : this()
        {
            ip_address = ip_s;
            tcp_port = p_n;
            user = usr;
            password = pa;
        }


        public bool Initialize()
        {
            bool ret = false;
            try
            {

                Open();

                if (OnConnected != null)
                {
                    OnConnected(this, new EventArgs());
                }

                ret = true;
            }
            catch (Exception ex)
            {
                //_Last_Error_Code = ErrorCodeNum.PressNotInit;
                string sName = this.GetType().FullName;
                ExManager.HandleException(ex, "Policy");
            }

            return ret;
        }



        public bool Open()
        {
            sock = Sockets.CreateTCPSocket(ip_address, tcp_port, true);
            client = new ClientInfo(sock, false); // Don't start receiving yet
            client.OnReadBytes += new ConnectionReadBytes(ReadData);
            client.OnClose += new ConnectionClosed(client_OnClose);
            client.BeginReceive();
            return true;
        }

        private void client_OnClose(ClientInfo ci)
        {
            try
            {
                if (OnConnectClosed != null)
                {
                    EventArgs arg = new EventArgs();
                    OnConnectClosed(this, arg);
                }
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            //if (!this.disposed)
            //{
            //    // If disposing equals true, dispose all managed 
            //    // and unmanaged resources.
            //    if (disposing)
            //    {
            //        // Dispose managed resources.
            //        //Components.Dispose();
            //    }
            CloseHandle();
            //}
            //disposed = true;
        }

        public void Close()
        {
            // Calls the Dispose method without parameters.
            Dispose();
        }

        ~LmiCamera()
        {
            Dispose(false);
        }

        private void DisConnect()
        {
            if (client == null)
                return;

            client.Close();
        }

        private bool CloseHandle()
        {
            try
            {
                DisConnect();
            }
            catch (Exception ex)
            {
                string sName = this.GetType().FullName;
                Logger.Write("Exception! +" + sName + "( " + ex.StackTrace + " )\n     Message: " + ex.Message);
            }
            return true;
        }


        private ByteBuilder receiveBuffer = new ByteBuilder();
        private void ReadData(ClientInfo ci, byte[] data, int len)
        {
            receiveBuffer.Clear();
            receiveBuffer.Add(data, 0, len);
            string str = Encoding.ASCII.GetString(receiveBuffer.Read(0, receiveBuffer.Length));
            if (str != "" && OnDataReceived != null)
            {
                CameraArgs arg = new CameraArgs(1, "", str, "");
                OnDataReceived(this, arg);
            }
            receiveBuffer.Clear();
        }


        private string current_tag = string.Empty;
        public bool SendCommand(string value, string tag)
        {
            bool ret = false;

            current_tag = tag;

            try
            {

                receiveBuffer.Clear();

                ByteBuilder b_s = new ByteBuilder();
                Byte[] value_arr = System.Text.Encoding.ASCII.GetBytes(value);


                if (value_arr.Length > 0)
                {
                    b_s.Add(System.Text.Encoding.ASCII.GetBytes(value));
                }
                else
                {
                    b_s.Add(new byte[] { 0 });
                }


                client.Send(b_s.Read(0, b_s.Length), b_s.Length);

                ret = true;
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
            return ret;
        }
    }

    public class CameraArgs : EventArgs
    {
        public readonly int Status;
        public readonly string Value;
        public readonly string ReceivedString;
        public readonly string Tag;

        public CameraArgs(int sta, string va, string re, string tag)
        {
            Status = sta;
            Value = va;

            ReceivedString = re;

            Tag = tag;
        }

        public override string ToString()
        {
            return ReceivedString;
        }
    }
}
